/*
 * Pidglet Plugin
 *
 * Copyright (C) 2008, Rudis Muiznieks <rudis@sitosis.com>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02111-1301, USA.
 *
 */

#ifdef HAVE_CONFIG_H
# include <config.h>
#endif

#ifndef PURPLE_PLUGINS
# define PURPLE_PLUGINS
#endif

#include <glib.h>

#ifndef G_GNUC_NULL_TERMINATED
# if __GNUC__ >= 4
#  define G_GNUC_NULL_TERMINATED __attribute__((__sentinel__))
# else
#  define G_GNUC_NULL_TERMINATED
# endif
#endif

#include <stdio.h>
#include <string.h>
#include <plugin.h>

#include "account.h"
#include "core.h"
#include "conversation.h"
#include "eventloop.h"
#include "internal.h"
#include "util.h"
#include "version.h"

static int checkTimer;

PurplePlugin *pidglet_plugin = NULL;

static void open_chat_window()
{
	char filename[256];
	char buffer[1024];
	FILE *file;
	PurpleBlistNode *gnode, *cnode, *bnode, *blist;
	PurpleBuddy *buddy;
	int cmp;
	PurpleConversation *conv;

	sprintf(filename, "%s" G_DIR_SEPARATOR_S "pidglet-cmd", purple_user_dir());

	file = g_fopen(filename, "r+");
	fgets(buffer, sizeof(buffer), file);
	fclose(file);

	blist = purple_blist_get_root();

	for(gnode = blist; gnode != NULL; gnode = gnode->next)
	{
		if (PURPLE_BLIST_NODE_IS_GROUP(gnode))
		{
			for(cnode = gnode->child; cnode != NULL; cnode = cnode->next)
			{
				if (PURPLE_BLIST_NODE_IS_CONTACT(cnode))
				{
					for(bnode = cnode->child; bnode != NULL; bnode = bnode->next)
					{
						if (PURPLE_BLIST_NODE_IS_BUDDY(bnode)){
							buddy = (PurpleBuddy *)bnode;
							if (PURPLE_BUDDY_IS_ONLINE(buddy))
							{
								cmp = strncmp(buddy->name, buffer, strlen(buddy->name));
								if (cmp == 0)
								{
									conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, buddy->account, buddy->name);
									purple_conversation_present(conv);
									break;
								}
							}
						}
					}
				}
			}
		}
	}

	remove(filename);
}

static gboolean
check_cmd_file()
{
	struct stat finfo;
	char filename[256];

	sprintf(filename, "%s" G_DIR_SEPARATOR_S "pidglet-cmd", purple_user_dir());

	if ((g_stat(filename, &finfo) == 0) && (finfo.st_size > 0))
	{
		open_chat_window();
	}

	return TRUE;
}

static void
clear_contact_xml()
{
	char filename[256];
	FILE *file;
	sprintf(filename, "%s" G_DIR_SEPARATOR_S "pidglet.xml", purple_user_dir());
	file = g_fopen(filename, "w");
	fprintf(file, "<OnlineBuddies />");
	fclose(file);
}

static void
update_contact_xml()
{
	char filename[256];
	FILE *file;
	PurpleBlistNode *gnode, *cnode, *bnode, *blist;
	PurpleContact *contact;
	PurpleBuddy *buddy;
	PurplePresence *presence;
	PurpleStatus *status;
	time_t bidle;

	sprintf(filename, "%s" G_DIR_SEPARATOR_S "pidglet.xml", purple_user_dir());
	blist = purple_blist_get_root();

	file = fopen(filename, "w");
	fprintf(file, "<OnlineBuddies>\n");

	for (gnode = blist; gnode != NULL; gnode = gnode->next)
	{
		if (PURPLE_BLIST_NODE_IS_GROUP(gnode))
		{
			for (cnode = gnode->child; cnode != NULL; cnode = cnode->next)
			{
				if (PURPLE_BLIST_NODE_IS_CONTACT(cnode))
				{
					contact = (PurpleContact *)cnode;
					for (bnode = cnode->child; bnode != NULL; bnode = bnode->next)
					{
						if (PURPLE_BLIST_NODE_IS_BUDDY(bnode))
						{
							buddy = (PurpleBuddy *)bnode;
							if (PURPLE_BUDDY_IS_ONLINE(buddy))
							{
								presence = purple_buddy_get_presence(buddy);
								status = purple_presence_get_active_status(presence);
								bidle = purple_presence_get_idle_time(presence);
								if(bidle > 0){
									bidle = time(NULL) - bidle;
								}

								fprintf(file, "\t<Buddy id=\"%s\" status=\"%s\" idle=\"%i\">%s</Buddy>\n", buddy->name, purple_status_get_name(status), bidle, purple_contact_get_alias(contact));
								break;
							}
						}
					}
				}
			}
		}
	}

	fprintf(file, "</OnlineBuddies>");
	fclose(file);
}
	
static void
buddy_signed_on_cb(PurpleBuddy *buddy, void *data)
{
	update_contact_xml();
}

static void
buddy_signed_off_cb(PurpleBuddy *buddy, void *data)
{
	update_contact_xml();
}

static void
buddy_status_changed_cb(PurpleBuddy *buddy, void *data)
{
	update_contact_xml();
}

static void
buddy_idle_changed_cb(PurpleBuddy *buddy, gboolean old_idle, gboolean idle, void *data)
{
	update_contact_xml();
}

static void
signed_on_cb(PurpleConnection *cb, void *data)
{
	update_contact_xml();
}

static void
signed_off_cb(PurpleConnection *cb, void *data)
{
	update_contact_xml();
}

static void
account_status_changed_cb(PurpleAccount *account, PurpleStatus *old, PurpleStatus *new, gpointer data)
{
	update_contact_xml();
}

static void
quitting_cb(void *data)
{
	clear_contact_xml();
}

static gboolean
plugin_load (PurplePlugin * plugin)
{
	void *core_handle = purple_get_core();
	void *blist_handle = purple_blist_get_handle();
	void *conn_handle = purple_connections_get_handle();
	void *accounts_handle = purple_accounts_get_handle();

	purple_signal_connect(accounts_handle, "account-status-changed", plugin, PURPLE_CALLBACK(account_status_changed_cb), NULL);

	purple_signal_connect(blist_handle, "buddy-status-changed", plugin, PURPLE_CALLBACK(buddy_status_changed_cb), NULL);

	purple_signal_connect(blist_handle, "buddy-signed-on",
						plugin, PURPLE_CALLBACK(buddy_signed_on_cb), NULL);
	purple_signal_connect(blist_handle, "buddy-signed-off",
						plugin, PURPLE_CALLBACK(buddy_signed_off_cb), NULL);
	purple_signal_connect(blist_handle, "buddy-idle-changed",
						plugin, PURPLE_CALLBACK(buddy_idle_changed_cb), NULL);

	purple_signal_connect(conn_handle, "signed-on", plugin, PURPLE_CALLBACK(signed_on_cb), NULL);

	purple_signal_connect(conn_handle, "signed-off", plugin, PURPLE_CALLBACK(signed_off_cb), NULL);

	purple_signal_connect(core_handle, "quitting",
						plugin, PURPLE_CALLBACK(quitting_cb), NULL);

	checkTimer = purple_timeout_add(1000, (GSourceFunc)check_cmd_file, NULL);

	pidglet_plugin = plugin; /* assign this here so we have a valid handle later */

	update_contact_xml();

	return TRUE;
}

static gboolean
plugin_unload(PurplePlugin *plugin)
{
	purple_timeout_remove(checkTimer);
	clear_contact_xml();
	return TRUE;
}

static PurplePluginInfo info = {
	PURPLE_PLUGIN_MAGIC,
	PURPLE_MAJOR_VERSION,
	PURPLE_MINOR_VERSION,
	PURPLE_PLUGIN_STANDARD,
	NULL,
	0,
	NULL,
	PURPLE_PRIORITY_DEFAULT,

	"core-rudism-pidglet",
	"Pidglet",
	"0.65",

	"A Windows Sidebar plugin for Pidgin",
	"A Windows Sidebar plugin for Pidgin",
	"Rudis Muiznieks <rudis@sitosis.com>",
	"http://www.rudism.com",


	plugin_load,
	plugin_unload,
	NULL,

	NULL,
	NULL,
	NULL,
	NULL, //plugin_actions
	NULL,
	NULL,
	NULL,
	NULL
};

static void
init_plugin (PurplePlugin * plugin)
{
}

PURPLE_INIT_PLUGIN (pidglet, init_plugin, info)
